/**
 * Copyright 2010 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package saig.engine.models;

import saig.engine.Context;
import saig.engine.models.enemies.BulletBill;
import saig.engine.models.enemies.Goomba;
import saig.engine.models.enemies.JumpingPiranhaPlant;
import saig.engine.models.enemies.KoopaTroopa;
import saig.engine.models.enemies.Shell;
import saig.engine.models.enemies.Spiny;
import saig.engine.models.enums.ModelType;
import saig.engine.models.interfaces.Colorable;
import saig.engine.models.interfaces.Flyable;


/**
 * Spawn Object, used to spawn other models from a level.
 * @author Adam
 * @version $Id$
 * 
 * Created on Aug 10, 2010 at 10:11:52 PM 
 */
public class Spawn implements Comparable<Spawn> {
	/**
	 * Whether or not the spawn is active or disabled.
	 */
	private boolean active;
	/**
	 * The color value of the model.
	 * @see saig.engine.models.interfaces.Colorable
	 */
	private int color;
	/**
	 * Whether or not the spawn is dead or alive.
	 */
	private boolean dead;
	/**
	 * The type of model to spawn.
	 */
	private ModelType type;
	/**
	 * Whether or not the model has wings.
	 * @see @see saig.engine.models.interfaces.Flyable
	 */
	private boolean wings;
	/**
	 * The spawn x point.
	 */
	private final int x;
	/**
	 * The spawn y point.
	 */
	private final int y;
	/**
	 * Constructs a Spawn with a template of the model that it will create.
	 * @param template The templte of the model to create.
	 * @param x The spawn x value.
	 * @param y The spawn y value.
	 */
	public Spawn(final Model template, int x, int y) {
		this.active = false;
		this.type = template.getType();
		if (template instanceof Flyable) {
			wings = ((Flyable) template).hasWings();
		}
		if (template instanceof Colorable) {
			color = ((Colorable) template).getColor();
		}
		this.x = x;
		this.y = y;
		this.dead = false;
	}
	/**
	 * Constructs a Spawn from another spawn.
	 * @param spawn The spawn.
	 */
	public Spawn(final Spawn spawn) {
		this.active = false;
		this.dead = false;
		this.type = spawn.type;
		this.x = spawn.x;
		this.y = spawn.y;
		this.wings = spawn.wings;
		this.color = spawn.color;
	}
	/**
	 * Constructs a Spawn.
	 * @see saig.engine.models.interfaces.Flyable
	 * @see saig.engine.models.interfaces.Colorable
	 * @param type The model type.
	 * @param wings If the model should have wings or not.
	 * @param color The color value.
	 * @param x The spawn x value.
	 * @param y The spawn y value.
	 */
	public Spawn(final ModelType type, final boolean wings, final int color, int x, int y) {
		this.active = false;
		this.type = type;
		this.wings = wings;
		this.color = color;
		this.x = x;
		this.y = y;
		this.dead = false;
	}
	/**
	 * {@inheritDoc}
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(final Spawn spawn) {
		int value = x - spawn.getX();
		if (value == 0) {
			value = y - spawn.getY();
		}
		return value;
	}
	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Spawn other = (Spawn) obj;
		if (active != other.active)
			return false;
		if (color != other.color)
			return false;
		if (type != other.type)
			return false;
		if (wings != other.wings)
			return false;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
	/**
	 * Returns color.
	 * @return the color.
	 */
	public int getColor() {
		return color;
	}
	/**
	 * Returns the spawned model.
	 * @param context The game context.
	 * @param x The x value to set the model to.
	 * @param y The y value to set the model to.
	 * @return The spawned model.
	 */
	public Model getModel(final Context context) {
		Model model = null;
		switch (type) {
		case MUSHROOM:
			model = new Mushroom(context);
			break;
		case FLOWER:
			model = new Flower(context);
			break;
		case BULLET_BILL:
			model = new BulletBill(context);
			break;
		case GOOMBA:
			model = new Goomba(context);
			break;
		case JUMPING_PIRANHA_PLANT:
			model = new JumpingPiranhaPlant(context);
			break;
		case KOOPA_TROOPA:
			model = new KoopaTroopa(context);
			break;
		case SHELL:
			model = new Shell(context);
			break;
		case SPINY:
			model = new Spiny(context);
			break;
		default:
			return null;
		}
		model.setSpawn(this);
		if (model instanceof Flyable) {
			((Flyable) model).setWings(wings);
		}
		if (model instanceof Colorable) {
			((Colorable) model).setColor(color);
		}
		model.setX(x);
		model.setY(y);
		return model;
	}
	/**
	 * Returns type.
	 * @return the type.
	 */
	public ModelType getType() {
		return type;
	}
	/**
	 * Returns x.
	 * @return the x.
	 */
	public int getX() {
		return x;
	}
	/**
	 * Returns y.
	 * @return the y.
	 */
	public int getY() {
		return y;
	}
	/**
	 * {@inheritDoc}
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (active ? 1231 : 1237);
		result = prime * result + color;
		result = prime * result + ((type == null) ? 0 : type.hashCode());
		result = prime * result + (wings ? 1231 : 1237);
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}
	/**
	 * Returns active.
	 * @return the active.
	 */
	public boolean isActive() {
		return active;
	}
	/**
	 * Returns dead.
	 * @return the dead.
	 */
	public boolean isDead() {
		return dead;
	}
	/**
	 * Returns wings.
	 * @return the wings.
	 */
	public boolean isWings() {
		return wings;
	}
	/**
	 * Sets active.
	 * @param active the active to set.
	 */
	public void setActive(final boolean active) {
		this.active = active;
	}
	/**
	 * Sets dead.
	 * @param dead the dead to set.
	 */
	public void setDead(boolean dead) {
		this.dead = dead;
	}
}
